#ifndef __D3D11RENDER_H_
#define __D3D11RENDER_H_


#include <d3d11.h>
#include <D3DX11.h>
#include <D3DX11async.h>
#include <D3Dcompiler.h>
#include <vector>
#include <string>
#include "d3d11types.h"
#include "dh_structures.h"




#ifdef RENDER_EXPORTS
	#define EXPORT_API __declspec(dllexport)
#else
	#define EXPORT_API __declspec(dllimport)
#endif
	


#define RELEASE_UNKNOWN(p) { if( (p) ) { (p)->Release();  (p) = NULL; } }
#define VALID_BUFFER(p)    ((p) >= 0)
#define VALID_HANDLE(p)    ((p) >= 0)



struct str_comp
{
	bool operator() ( const char* s1, const char* s2 )
	{
		return strcmp( s1, s2 ) < 0;
	}
};



#define			DEFAULT_HANDLE			-2
#define			INVALID_HANDLE			-1


#define			MAX_VERTEX_STREAMS		16


#define			CLEAR_BACKBUFFER		0x01
#define			CLEAR_ZBUFFER			0x02
#define			CLEAR_STENCILBUFFER		0x04

#define			USAGE_STATIC			0x01
#define			USAGE_DYNAMIC			0x02

#define			INSTANCE_DATA			0x10
#define			VERTEX_DATA				0x20



struct dh_render_init
{	
	unsigned int		displayWidth;
	unsigned int		displayHeight;
	unsigned int		refreshRate;

	unsigned int		depthBits;
	unsigned int		stencilBits;
	
	bool				windowed;
	
	HWND				window;
};



//-=-=-=--=-=-=-=-=--=-=-=-=-=--=-=-=-=-=--=-=-=-=-=--=-=//
//			DATA DESCRIPTORS							 //
//-=-=-=--=-=-=-=-=--=-=-=-=-=--=-=-=-=-=--=-=-=-=-=--=-=//
struct dh_vertex_element
{
	// This is mandatory for D3D11 input stream binding //
	// The user must pass technique and pass information with //
	// the vertex format to bind to the effect //
	int					shaderHandle;
	std::string			techniqueName;
	int					techniquePass;
	
	std::string			semantic;
	unsigned int		semanticIndex;
	DATA_FORMAT			format;					
	unsigned int		inputSlot;
	unsigned int		alignmentBytes;
	unsigned char		inputClassType;			// Either INSTANCE_DATA or VERTEX_DATA
	unsigned int		nInstances;				// Number of instances if inputClassType is INSTANCE_DATA
};



class EXPORT_API dh_renderer
{
	public:
	
		dh_renderer();
		~dh_renderer();
		
		
		bool	InitializeRenderer( const dh_render_init& init );
		
		void	ClearBackBuffer( const unsigned char clearFlags, float r, float g, float b );
		void	ClearDepthStencilBuffer( unsigned char buf, float depthClear, unsigned char stencilClear );
		void	PresentScene();
		
		
		int		CreateVertexBuffer( void* buf, int bufSize, unsigned char usage );
		int		CreateIndexBuffer( void* buf, int nIndices, unsigned char usage );
		int		CreateVertexFormat( const dh_vertex_element* desc, int nElements );
		
		int		CreateVertexShader(char* shaderText);
		
		bool	BindVertexBuffers( int* buffers, unsigned int* bufferSizes, unsigned int* bufferOffsets, unsigned int nBuffers );
		bool	BindIndexBuffer( int buffer, unsigned int offset );
		
		void	DeleteVertexBuffer( const int handle );
		void	DeleteIndexBuffer( const int handle );
		
		
		std::string		GetBestVertexProfile() { return VERTEX_SHADER_PROFILES[featureLevelIndex]; }
		std::string		GetBestPixelProfile()  { return PIXEL_SHADER_PROFILES[featureLevelIndex]; }
		std::string		GetBestGeometryProfile() { return GEOMETRY_SHADER_PROFILES[featureLevelIndex]; }
		std::string		GetBestHullProfile() { return HULL_SHADER_PROFILES[featureLevelIndex]; }
		std::string		GetBestDomainProfile() { return DOMAIN_SHADER_PROFILES[featureLevelIndex]; }
		std::string		GetBestComputeProfile() { return COMPUTE_SHADER_PROFILES[featureLevelIndex]; }
		std::string		GetBestEffectProfile() { return EFFECT_PROFILES[featureLevelIndex]; }

	private:
	

	
		ID3D11Device*			pDevice;
		IDXGISwapChain*			pSwapChain;
		D3D_FEATURE_LEVEL		curFeatureLevel;
		ID3D11DeviceContext*	pDeviceContext;
		ID3D11RenderTargetView* pRTV;
		ID3D11DepthStencilView* pDSV;
		
		std::vector <ID3D11Buffer*>			vVertexBuffers;
		std::vector <ID3D11Buffer*>			vIndexBuffers;
		std::vector <ID3D11InputLayout*>	vVertexFormats;
		std::vector <ID3D11VertexShader*>	vVertexShaders;
		
		std::vector <int>				vVertexBufferSlots;
		std::vector <int>				vIndexBufferSlots;
		
		unsigned int			featureLevelIndex;
};



extern dh_renderer*		gpRenderer;



#endif